extends CharacterBody2D

class_name Player

# 添加状态
enum State {NORMAL, DASHING, INPUT_DISABLED}
# 当前的状态
var currentState := State.NORMAL
# 是否为新的状态
var isStateNew := true
	

var jumpSpeed: int = 300	# 跳跃速度
var horizontalAcceleration: int = 2000	# 水平加速度
var MaxHorizontalSpeed: int = 140	# 最大水平速度
var jumpTerminationMultiplier: int = 4	# 跳跃终止乘数
var gravity: int = 1000	# 重力加速度
var maxDashSpeed: int = 500
var minDashSpeed: int = 200
var player_nodes
var isDead: bool = false
var moveVec: Vector2 = Vector2.ZERO
var hasDash := false
var hasDoubleJump := false

@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@onready var coyote_timer: Timer = $CoyoteTimer
@onready var find_danger: Area2D = $FindDanger
@onready var player_death_scene = preload("res://Player/player_death.tscn")
@onready var find_spring: Area2D = $FindSpring
@onready var attack_area: Area2D = $AttackArea
@onready var find_danger_collision_shape2d: CollisionShape2D = $FindDanger/CollisionShape2D
@onready var attack_collisionshape: CollisionShape2D = $AttackArea/CollisionShape2D
@onready var dash_trail: CPUParticles2D = $DashTrail
const FOOTSTEP = preload("res://Player/footstep.tscn")



# 初始化
func _ready() -> void:
	animated_sprite_2d.frame_changed.connect(on_frame_changed)
	find_danger.area_entered.connect(on_find_danger)
	player_nodes = get_tree().get_nodes_in_group("player_nodes")[0]
	attack_area.area_entered.connect(on_enemy_attacked)
	
func on_frame_changed():
	if (animated_sprite_2d.animation == "run" && animated_sprite_2d.frame == 0):
		spawn_footstep()
		$FootStepAudioPlayer.play()

func spawn_footstep():
	var foot_step_instance = FOOTSTEP.instantiate()
	foot_step_instance.emitting = true
	foot_step_instance.global_position = $FootPos.global_position
	get_parent().add_child(foot_step_instance)
	
func on_enemy_attacked(area2d):
	area2d.get_parent().die()
	
# 处理危险碰撞
func on_find_danger(_area_2d):
	if (isDead): 
		return	# 防止同时踩到两个地刺报错
	var player_group = get_tree().get_nodes_in_group("players")
	if (player_group.size() > 0):	# 为防止多次死亡，判断玩家是否存存活，只有存活才杀死玩家
		call_deferred("die")
		isDead = true

# 获取输入并存入一个二维向量数组
func get_movement_vector():	
	var moveVec = Vector2.ZERO	
	moveVec.x = Input.get_action_strength("right") - Input.get_action_strength("left")
	moveVec.y = -1 if Input.is_action_just_pressed("jump") else 0
	return moveVec

func _process(delta: float) -> void:
	match currentState:
		State.NORMAL:
			process_normal(delta)
		State.DASHING:
			process_dashing(delta)
		State.INPUT_DISABLED:
			process_input_diabled(delta)
	isStateNew = false
			

func process_input_diabled(delta):
	if (isStateNew):
		animated_sprite_2d.play("default")
	velocity.y += gravity * delta
	velocity.x = 0
	move_and_slide()

func update_dash_property():
	dash_trail.emitting = false
	find_danger_collision_shape2d.disabled = false
	attack_collisionshape.disabled = true

func change_state(newState):
	currentState = newState
	isStateNew = true

# 物理更新
func process_normal(delta: float) -> void:
	# 获取移动向量
	moveVec = get_movement_vector()
		
	# 增加水平加速度(每秒都需要执行所以乘以delta)
	velocity += moveVec * horizontalAcceleration * delta
	
	# 水平减速
	if (moveVec.x == 0):
		velocity.x = lerpf(velocity.x, 0, pow(2, -50 * delta))
	
	# 限制水平最大速度
	velocity.x = clamp(velocity.x, -MaxHorizontalSpeed, MaxHorizontalSpeed)
	
	# 检测跳跃(按下按键+在地面/在土狼时间中)
	if (moveVec.y < 0 && (is_on_floor() || !coyote_timer.is_stopped() || hasDoubleJump)):	
		dash_trail.emitting = true
		velocity.y = moveVec.y * jumpSpeed
		if (!is_on_floor() && coyote_timer.is_stopped()):
			hasDoubleJump = false
		coyote_timer.stop()
	
	# 提前结束跳跃
	if (velocity.y < 0 and not Input.is_action_pressed("jump")):
		velocity.y += gravity * jumpTerminationMultiplier * delta
	else:
		velocity.y += gravity * delta	# 施加重力
		
	# 上一帧是否在地面
	var was_on_floor = is_on_floor()
	
	# 滑动
	move_and_slide()
	
	# 第一次离开地面开启土狼时间
	if (not is_on_floor() and was_on_floor):
		coyote_timer.start()
	if (not was_on_floor and is_on_floor()):
		spawn_footstep()

	# 在地面刷新冲刺能力
	if (is_on_floor()):
		dash_trail.emitting = false
		hasDash = true
		hasDoubleJump = true
	
	# 检测是否进入冲刺状态
	if (Input.is_action_just_pressed("dash") && hasDash):
		update_dash_property()
		call_deferred("change_state", State.DASHING)
		hasDash = false
	
	# 更新动画
	update_animation()

func process_dashing(delta: float) -> void:
	if (isStateNew):
		$DashAudioPlayer.play()
		dash_trail.emitting = true
		find_danger_collision_shape2d.disabled = true
		attack_collisionshape.disabled = false
		animated_sprite_2d.play("jump")
		var moveVec: Vector2 = get_movement_vector()
		var moveMod := 1
		if (moveVec.x != 0):
			moveMod = sign(moveVec.x)
		else:
			moveMod = 1 if animated_sprite_2d.flip_h == true else -1
		velocity = Vector2(maxDashSpeed * moveMod, 0)
	move_and_slide()
	velocity.x = lerpf(0, velocity.x, pow(2, -8 * delta))
	
	if (abs(velocity.x) < minDashSpeed):
		call_deferred("change_state", State.NORMAL)
		update_dash_property()


# 更新动画
func update_animation():
	# 获取输入向量
	var moveVec = get_movement_vector()
	
	# 不在地面播放跳跃
	if (! is_on_floor()):
		animated_sprite_2d.play("jump")
	# 按下左右键移动播放跑步
	elif (moveVec.x != 0):
		animated_sprite_2d.play("run")
	# 其他
	else:
		animated_sprite_2d.play("default")
	
	# 只在按下移动键时处理翻转
	if (moveVec.x != 0):
		animated_sprite_2d.flip_h = true if moveVec.x > 0 else false

# 杀死玩家创建尸体
func die():
	var player_death_instance = player_death_scene.instantiate()
	player_death_instance.global_position = global_position
	player_death_instance.velocity = velocity
	player_nodes.add_child(player_death_instance)
	call_deferred("queue_free")

func on_passed_level():
	change_state(State.INPUT_DISABLED)
